import { forwardRef } from 'react'
import { GetProps, GetRef, message, Upload } from 'antd'

import { apiUpload } from './apis'

/** 附件上传请求入参 */
export interface ICusUploadReq {
  /** 模块类型（主目录）： 1-用户头像模块 2-产品模块 3-供应商模块 4-公共地址模块 5-字典模块 6-客户模块 7-导师模块 8-服务商模块 */
  moduleType: number
  /** 子目录，默认为当前 userId */
  userId?: string
}

/** 附件上传响应 */
export interface ICusUploadRes {
  /** 对象在oss的路径 */
  objectName: string
  /** 文件名称 */
  originalFilename: string
  /** 文件对象完整url */
  url: string
}

/** CusUpload 组件 Props */
export type TCusUploadProps = Omit<
  GetProps<typeof Upload> & {
    /** 请求入参 */
    reqData: ICusUploadReq
    /** 支持拖拽上传 */
    dragger?: boolean
  },
  'customRequest' | 'action' | 'method' | 'headers' | 'data' | 'withCredentials' | 'directory'
>

/** antd Upload 组件封装 */
export const CusUpload = Object.assign(
  forwardRef<GetRef<typeof Upload>, TCusUploadProps>(function CusUpload(
    { reqData, dragger, beforeUpload, ...rest },
    ref,
  ) {
    const Comp = dragger ? Upload.Dragger : Upload
    return (
      <Comp
        {...rest}
        ref={ref}
        beforeUpload={(...args) => {
          for (const { name } of args[1]) {
            if (name.includes('?') || name.includes('#')) {
              message.error(`文件名不能包含?#`)
              return Upload.LIST_IGNORE
            }
          }
          return beforeUpload?.(...args)
        }}
        customRequest={async options => {
          const { onProgress, onError, onSuccess, file } = options
          try {
            const res = await apiUpload(
              { file, attachType: 2 },
              {
                onUploadProgress: ({ loaded, total }) => {
                  if (!total) return
                  const percent = Math.round((loaded * 100) / total)
                  onProgress?.({ percent })
                },
              },
            )
            onSuccess?.(res)
          } catch (err) {
            onError?.(err instanceof Error ? err : new Error())
            throw err
          }
        }}
      />
    )
  }),
  {
    /** 在 beforeUpload 中返回该值则停止上传，且列表中不展示 */
    LIST_IGNORE: Upload.LIST_IGNORE,
  },
)
